-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.

local lu = require 'luaunit'

local client = require 'general_hardware.client'
local upgrade = require "upgrade_subject.upgrade_subject"
local dpu_service = require 'dpu_service.dpu_service'
local upgrade_service_handle = require 'mcu.upgrade.upgrade_service.upgrade_service_handle'

local retimer_service = require 'retimer.upgrade.retimer_upg_service'
local sr_upg_service = require 'sr_upg_service.sr_upg_service'
local cpld_service = require 'unit_manager.class.logic_fw.signal'
local fpga_service = require 'unit_manager.class.logic_fw.fpga.fpga_signal'

local utils = require 'dpu_service.utils'
local parser_cfg = require 'sr_upg_service.parser_cfg'
local retimer_parser = require 'retimer.upgrade.parser_cfg'
local fructl = require 'mcu.upgrade.fructl_handler'


local function stub_function_list()
        -- 监听升级信号
        client.SubscribeUpdateServiceUpdateServiceUpgradePrepareSignal = function ()
        end
        client.SubscribeUpdateServiceUpdateServiceUpgradeProcessSignal = function ()
        end
        client.SubscribeUpdateServiceUpdateServiceUpgradeFinishSignal = function ()
        end
        client.SubscribeFirmwareActiveFirmwareActiveActiveProcessSignal = function ()
        end
        utils.get_cfgs = function ()
            return {}
        end
end

TestUpgradeSubject = {}

-- 测试用例描述：dpu升级流程
-- 预置条件：创建dpu服务，创建subject对象
-- 操作步骤：
-- 1.通过init注册observer
-- 2.模拟收到prepare/process/finish信号
-- 预期结果：1.observer注册正常；2.正确走入dpu prepare/process/finish流程
--[[
function TestUpgradeSubject:test_dpu_upgrade()
    stub_function_list()
    local subject_service = upgrade.new()
    subject_service:init()
    local dpu = dpu_service.new()
    dpu.test_flag = "dpu object"
    dpu:init({})

    local dpu_firmware_list = {"DPUMcu", "DPUCpld", "DPUVrd", "Mcu"}
    for i = 1, #dpu_firmware_list do
        local firmware_type = dpu_firmware_list[i]
        local dpu_observer = subject_service.upgrade_observers[firmware_type]
        if not dpu_observer then
            lu.assertIsTrue(dpu_firmware_list[i] == "Mcu")
        else
            lu.assertIsTrue(dpu_observer.test_flag == "dpu object")
        end
    end

    utils.get_firmware_uid = function ()
        return true
    end
    
    local ok = pcall(function()
        return subject_service:on_upgrade_prepare(_, 1, 'Mcu', '/dev/shm/upgrade/123456/name', _, _)
    end)
    lu.assertIsTrue(ok == true)

    dpu.upgradable_cfgs = {
        name = 'Firmware1',
        component_id = 1,
        component_id_ex = 2,
        board_id = 3
    }
    local ok2 = pcall(function()
        return subject_service:on_upgrade_process(_, 1, 'Mcu', '/dev/shm/upgrade/123456/name')
    end)
    lu.assertIsTrue(ok2 == true)
    local ok3 = pcall(function ()
        return subject_service:on_upgrade_finish(_, 1, 'Mcu')
    end)
    lu.assertIsTrue(ok3 == true)
end ]]

-- 测试用例描述：mcu升级流程
-- 预置条件：创建mcu服务，创建subject对象
-- 操作步骤：
-- 1.通过init注册observer
-- 2.模拟收到prepare/process/active信号
-- 预期结果：1.observer注册正常；2.正确走入mcu prepare/process/active流程
function TestUpgradeSubject:test_mcu_upgrade()
    stub_function_list()
    local subject_service = upgrade.new()
    subject_service:init()
    local mcu = upgrade_service_handle.new()
    mcu.test_flag = "mcu object"
    mcu:init({}, {}, {})

    local mcu_firmware_list = {"Mcu", "Vrd", "Vdm"}
    for i = 1, #mcu_firmware_list do
        local firmware_type = mcu_firmware_list[i]
        local mcu_observer = subject_service.upgrade_observers[firmware_type]
        lu.assertIsTrue(mcu_observer.test_flag == "mcu object")
    end
    local mcu_observer = subject_service.active_observers["VRD"]
    lu.assertIsTrue(mcu_observer.test_flag == "mcu object")

    utils.get_firmware_uid = function ()
        return false
    end

    local ok = pcall(function ()
        return subject_service:on_upgrade_prepare(_, 1, 'Mcu', '/dev/shm/upgrade/123456/name', '/dev/shm/upgrade/hpm')
    end)
    lu.assertIsTrue(ok == true)

    mcu.mcu_upg_instances = {
        Mcu = {
            cfgs = {
                Firmware1 = {
                    name = 'Firmware1',
                    component_id = 29,
                    component_idex = 0
                }
            }
        }
    }

    local ok2 = pcall(function ()
        return subject_service:on_upgrade_process(_, 1, 'Mcu', '/dev/shm/upgrade/123456/name', '/dev/shm/upgrade/hpm')
    end)
    lu.assertIsTrue(ok2 == true)

    local ok3 = pcall(function ()
        return subject_service:on_active_process(_, 1, 'VRD')
    end)
    lu.assertIsTrue(ok3 == true)
end

-- 测试用例描述：sr升级流程
-- 预置条件：创建sr服务，创建subject对象
-- 操作步骤：
-- 1.通过init注册observer
-- 2.模拟收到prepare/process信号
-- 预期结果：1.observer注册正常；2.正确走入sr prepare/process流程
function TestUpgradeSubject:test_sr_upgrade()
    stub_function_list()
    local subject_service = upgrade.new()
    subject_service:init()

    local sr_service = sr_upg_service.new()
    sr_service.test_flag = "sr object"
    sr_service:init({})

    local observer = subject_service.upgrade_observers["HWSR"]
    lu.assertIsTrue(observer.test_flag == "sr object")

    parser_cfg.get_cfgs = function ()
        local cfgs = {}
        cfgs[1]={component_id_ex = 127}
        return cfgs
    end

    local parameters = {["ActiveMode"] = "Immediately"}
    local ok = pcall(function ()
        return subject_service:on_upgrade_prepare(_, 1, 'HWSR', '', _, parameters)
    end)
    lu.assertIsTrue(ok == true)

    local ok2 = pcall(function ()
        return subject_service:on_upgrade_process(_, 1, 'HWSR', '/dev/shm/upgrade/123456/name')
    end)
    lu.assertIsTrue(ok2 == true)
end

-- 测试用例描述：retimer升级流程
-- 预置条件：创建retimer服务，创建subject对象
-- 操作步骤：
-- 1.通过init注册observer
-- 2.模拟收到prepare/process信号
-- 预期结果：1.observer注册正常；2.正确走入retimer prepare/process流程
function TestUpgradeSubject:test_retimer_upgrade()
    stub_function_list()
    local subject_service = upgrade.new()
    subject_service:init()

    local retimer = retimer_service.new()
    retimer.test_flag = "retimer object"
    retimer:init({}, {})

    local observer = subject_service.upgrade_observers["Retimer"]
    lu.assertIsTrue(observer.test_flag == "retimer object")

    retimer_parser.get_cfgs = function ()
        local cfgs = {}
        cfgs[1]={component_id_ex = 16753977}
        return cfgs
    end
    local ok = pcall(function ()
        return subject_service:on_upgrade_prepare(_, 1, 'Retimer', '/dev/shm/upgrade/123456/name')
    end)
    lu.assertIsTrue(ok == true)
    local ok2 = pcall(function ()
        return subject_service:on_upgrade_process(_, 1, 'Retimer', '/dev/shm/upgrade/123456/name')
    end)
    lu.assertIsTrue(ok2 == true)
end

-- 测试用例描述：cpld升级流程
-- 预置条件：创建cpld服务，创建subject对象
-- 操作步骤：
-- 1.通过init注册observer
-- 2.模拟收到prepare/process/active信号
-- 预期结果：1.observer注册正常；2.正确走入cpld prepare/process/active流程
function TestUpgradeSubject:test_cpld_upgrade()
    stub_function_list()
    local subject_service = upgrade.new()
    subject_service:init()

    local cpld = cpld_service.init({}, {}, {})
    cpld.test_flag = "cpld object"

    local firmware_list = {"Cpld", "BP_Cpld"}
    for i = 1, #firmware_list do
        local firmware_type = firmware_list[i]
        local observer = subject_service.upgrade_observers[firmware_type]
        lu.assertIsTrue(observer.test_flag == "cpld object")
    end
    local cpld_observer = subject_service.active_observers["CPLD"]
    lu.assertIsTrue(cpld_observer.test_flag == "cpld object")

    local ok = pcall(function ()
        return subject_service:on_upgrade_prepare(_, 1, 'Cpld', '/dev/shm/upgrade/123456/name')
    end)
    lu.assertIsTrue(ok == true)
    local ok2 = pcall(function ()
        return subject_service:on_upgrade_process(_, 1, 'Cpld', '/dev/shm/upgrade/123456/name')
    end)
    lu.assertIsTrue(ok2 == true)
    local ok3 = pcall(function ()
        return subject_service:on_active_process(_, 1, 'CPLD')
    end)
    lu.assertIsTrue(ok3 == true)
end

-- 测试用例描述：fpga升级流程
-- 预置条件：创建fpga服务，创建subject对象
-- 操作步骤：
-- 1.通过init注册observer
-- 2.模拟收到prepare/process/active信号
-- 预期结果：1.observer注册正常；2.正确走入fpga prepare/process/active流程
function TestUpgradeSubject:test_fpga_upgrade()
    stub_function_list()
    local subject_service = upgrade.new()
    subject_service:init()

    local fpga = fpga_service.init({}, {}, {})
    fpga.test_flag = "fpga object"

    local observer = subject_service.upgrade_observers["FPGA"]
    lu.assertIsTrue(observer.test_flag == "fpga object")

    local fpga_observer = subject_service.active_observers["FPGA"]
    lu.assertIsTrue(fpga_observer.test_flag == "fpga object")

    local ok = pcall(function ()
        return subject_service:on_upgrade_prepare(_, 1, 'FPGA', '/dev/shm/upgrade/123456/name')
    end)
    lu.assertIsTrue(ok == true)

    fructl.get_chassis_power_status = function ()
        return "ON"
    end

    local ok2 = pcall(function ()
        return subject_service:on_upgrade_process(_, 1, 'FPGA', '/dev/shm/upgrade/123456/name')
    end)
    lu.assertIsTrue(ok2 == true)
    local ok3 = pcall(function ()
        return subject_service:on_active_process(_, 1, 'FPGA')
    end)
    lu.assertIsTrue(ok3 == true)
end